//#define USE_DUNGEONBUDDY_DLL
using System;
using System.Collections.Generic;
using Styx;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;
namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Wrath_of_the_Lich_King
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
    namespace Bots.DungeonBuddy.Dungeon_Scripts.Wrath_of_the_Lich_King
#endif
{
    public class UtgardeKeep : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId { get { return 202; } }

        public override WoWPoint Entrance { get { return new WoWPoint(1235.027, -4860.007, 41.24839); } }

        public override WoWPoint ExitLocation { get { return new WoWPoint(144.4507, -88.97738, 12.55168); } }

        private readonly WoWPoint _ignoreDragonflayerPackLoc = new WoWPoint(331.5634, 0.776747, 22.7549);

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                ret =>
                {
                    // fix for HB trying to run through a flaming wall of fire to get to this pack
                    if ((ret.Entry == 24078 || ret.Entry == 24079 || ret.Entry == 24080) && !ret.ToUnit().Combat && ret.Location.DistanceSqr(_ignoreDragonflayerPackLoc) <= 20 * 20)
                        return true;
                    return false;
                });
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var obj in incomingunits)
            {
                var unit = obj as WoWUnit;
                if (unit != null)
                {
                    if (unit.Entry == FrostTombId) // Frost Tomb
                        outgoingunits.Add(unit);
                }
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var priority in units)
            {
                var unit = priority.Object as WoWUnit;
                if (unit != null)
                {
                    if (unit.Entry == FrostTombId && Me.IsDps())
                        priority.Score += 1000;

                    if ((unit.Entry == KarvaldTheConstructorGhostId || unit.Entry == DalronnTheControllerId) && Me.IsDps())
                        priority.Score -= 500;
                }
            }
        }

        public override void OnEnter()
        {
            BossManager.OnBossKill += BossManager_OnBossKill;
        }

        public override void OnExit()
        {
            BossManager.OnBossKill -= BossManager_OnBossKill;
        }

        readonly WaitTimer _waitForBossToRespawn = new WaitTimer(TimeSpan.FromSeconds(20));
        public override bool IsComplete
        {
            get
            {
                return !ScriptHelpers.IsBossAlive("Ingvar the Plunderer") && _waitForBossToRespawn.IsFinished && !StyxWoW.Me.Combat;
            }
        }

        void BossManager_OnBossKill(Profiles.Handlers.Boss boss)
        {
            if (boss.Entry == IngvarThePlunderer)
            {
                _waitForBossToRespawn.Reset();
                Logger.Write("We killed Ingvar once, lets do it again.");
            }
        }

        #endregion

        [EncounterHandler(24137, "Dark Ranger Marrah", Mode = CallBehaviorMode.Proximity, BossRange = 30)]
        public Composite QuestPickupHandler()
        {
            WoWUnit unit = null;
            const int ingvarMustDieQuestId = 11262;
            const int aScoreToSettleQuestId = 30112;

            return new PrioritySelector(
                ctx => unit = ctx as WoWUnit,
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.Available,
                    new PrioritySelector(
                        new Decorator(ctx => !Me.QuestLog.ContainsQuest(ingvarMustDieQuestId) && !Me.QuestLog.GetCompletedQuests().Contains(ingvarMustDieQuestId),
                            ScriptHelpers.CreatePickupQuest(() => unit, ingvarMustDieQuestId)),
                        new Decorator(ctx => !Me.QuestLog.ContainsQuest(aScoreToSettleQuestId) && !Me.QuestLog.GetCompletedQuests().Contains(aScoreToSettleQuestId),
                            ScriptHelpers.CreatePickupQuest(() => unit, aScoreToSettleQuestId))
                        )),
                new Decorator(
                    ctx => !Me.Combat && !ScriptHelpers.WillPullAggroAtLocation(unit.Location) && unit.QuestGiverStatus == QuestGiverStatus.TurnIn,
                    ScriptHelpers.CreateTurninQuest(() => unit)));
        }

        private const uint KarvaldTheConstructorGhostId = 27389;
        private const uint DalronnTheControllerId = 27390;

        private const uint FrostTombId = 23965;
        private LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }


        private const uint IngvarThePlunderer = 23954;
        [ObjectHandler(186611, "Glowing Anvil", ObjectRange = 120)]
        public Composite GlowingAnvilHandler()
        {
            var movetoLoc1 = new WoWPoint(306.7014, -36.75847, 24.67742);
            var movetoLoc2 = new WoWPoint(344.295, -56.70161, 22.7549);
            var movetoLoc3 = new WoWPoint(397.0732, -41.2756, 22.75489);

            return new PrioritySelector(
                new Decorator(
                    ctx =>
                    StyxWoW.Me.Location.DistanceSqr(movetoLoc1) < 30 * 30 && Targeting.Instance.IsEmpty() && (StyxWoW.Me.IsTank() || ScriptHelpers.Tank == null || ScriptHelpers.Tank.DistanceSqr > 50 * 50),
                    new Action(ctx => Navigator.MoveTo(movetoLoc2))),
                new Decorator(
                    ctx =>
                    StyxWoW.Me.Location.DistanceSqr(movetoLoc2) < 30 * 30 && Targeting.Instance.IsEmpty() && (StyxWoW.Me.IsTank() || ScriptHelpers.Tank == null || ScriptHelpers.Tank.DistanceSqr > 50 * 50),
                    new Action(ctx => Navigator.MoveTo(movetoLoc3))));
        }

        [EncounterHandler(23953, "Prince Keleseth")]
        public Composite PrinceKelesethEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit
                );
        }

        [EncounterHandler(24201, "Dalronn the Controller")]
        public Composite DalronnTheControllerEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit
                );
        }

        [EncounterHandler(24200, "Skarvald the Constructor")]
        public Composite SkarvaldTheConstructorEncounter()
        {
            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit
                );
        }

        [EncounterHandler(23954, "Ingvar the Plunderer")]
        public Composite IngvarThePlundererEncounter()
        {
            const uint IngvarThrowTargetId = 23996;

            AddAvoidObject(ctx => true, 8, 23996);

            WoWUnit boss = null;
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateTankFaceAwayGroupUnit(8),
                // avoid the cleave
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(ctx => !StyxWoW.Me.IsTank() && boss.Distance <= 8 && boss.CurrentTargetGuid != Me.Guid && !boss.IsMoving, () => boss, new ScriptHelpers.AngleSpan(0, 150))
                );
        }
    }
}